package com.qh.book.service.impl;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.transaction.Transactional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;

import com.qh.book.dataobj.Book;
import com.qh.book.dto.CartDTO;
import com.qh.book.enums.BookStatusEnum;
import com.qh.book.enums.ResultEnum;
import com.qh.book.exception.BsException;
import com.qh.book.repository.BookRepository;
import com.qh.book.service.BookService;

import freemarker.template.utility.StringUtil;

/**
 * 
 * @author qihong
 * @date 2017年9月16日 下午9:03:26 
 * @Description: TODO
 */
@Transactional
@Service
public class BookServiceImpl implements BookService{
	
	private final Logger log = LoggerFactory.getLogger(BookServiceImpl.class);
	
	@Autowired
	private BookRepository bookRepository;

	@Override
	public Book findOne(String bookId) {
		Book book = bookRepository.findOne(bookId);
		return book;
	}

	@Override
	public Page<Book> findAll(Pageable pageable) {
		return bookRepository.findAll(pageable);
	}

	@Override
	public Book save(Book book) {
		
		return bookRepository.save(book);
	}

	@Override
	public void saveBatch(List<Book> bookList) {
		for (Book book : bookList) {
			bookRepository.save(book);
		}
	}

	@Override
	public void increaseStock(List<CartDTO> cartDTOList) {
		for (CartDTO cartDTO : cartDTOList) {
			Book book = bookRepository.findOne(cartDTO.getBookId());
			if(book == null) {
				log.error("【增加库存】没有该书籍ID={}",cartDTO.getBookId());
				throw new BsException(ResultEnum.BOOK_NOT_EXIST);
			}
			Integer newStock = book.getBookStock() + cartDTO.getBookQuantity();
			book.setBookStock(newStock);
			bookRepository.save(book);
		}
		
	}

	@Override
	public void decreaseStock(List<CartDTO> cartDTOList) {
		for (CartDTO cartDTO : cartDTOList) {
			Book book = bookRepository.findOne(cartDTO.getBookId());
			if(book == null) {
				log.error("【增加库存】书籍不存在，ID={}",cartDTO.getBookId());
				throw new BsException(ResultEnum.BOOK_NOT_EXIST);
			}
			Integer newStock = book.getBookStock() - cartDTO.getBookQuantity();
			if(newStock<0) {
				log.error("【减少库存】库存不足，ID={},剩余={},需减少={}",book.getBookId(),book.getBookStock(),cartDTO.getBookQuantity());
				throw new BsException(ResultEnum.BOOK_NOT_ENOUGH);
			}
			book.setBookStock(newStock);
			bookRepository.save(book);
		}
		
		
	}

	@Override
	public Book onSale(String bookId) {
		Book book = bookRepository.findOne(bookId);
		if(book.getBookStatus().equals(BookStatusEnum.UP.getCode())) {
			log.error("【商品上架】上架失败,{}书籍已上架",bookId);
			throw new BsException(ResultEnum.BOOK_ONSALE_FAIL);
			
		}
		book.setBookStatus(BookStatusEnum.UP.getCode());
		Book updateBook = bookRepository.save(book);
		log.info("【商品上架】ID={},Name={}",bookId,book.getBookName());
		return updateBook;
	}

	@Override
	public Book offSale(String bookId) {
		Book book = bookRepository.findOne(bookId);
		if(book.getBookStatus().equals(BookStatusEnum.DOWN.getCode())) {
			log.error("【商品上架】下架失败,{}书籍已下架",bookId);
			throw new BsException(ResultEnum.BOOK_OFFSALE_FAIL);
		}
		book.setBookStatus(BookStatusEnum.DOWN.getCode());
		Book updateBook = bookRepository.save(book);
		log.info("【商品下架】ID={},Name={}",bookId,book.getBookName());
		return updateBook;
	}

	@Override
	public Page<Book> findUpAll(Pageable pageable) {
		return bookRepository.findByBookStatus(BookStatusEnum.UP.getCode(), pageable);
	}

	@Override
	public Page<Book> findAll(Book book, Pageable pageable) {
		
		Specification<Book> spec = new Specification<Book>() {
			
			@Override
			public Predicate toPredicate(Root<Book> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				List<Predicate> list = new ArrayList<Predicate>();
				
				if(!StringUtils.isEmpty(book.getBookName())) {
					list.add(cb.like(root.get("bookName").as(String.class),"%"+book.getBookName()+"%"));
				}
				if(!StringUtils.isEmpty(book.getBookStatus())) {
					list.add(cb.equal(root.get("bookStatus").as(Integer.class), BookStatusEnum.UP.getCode()));
				}
				Predicate[] restrictions = new Predicate[list.size()];
				return cb.and(list.toArray(restrictions));
			}
		};
		
		return bookRepository.findAll(spec, pageable);
	}

	@Override
	public List<Book> findByBookIdIn(List<String> bookIdList) {
		
		return bookRepository.findByBookIdIn(bookIdList);
	}

	
}
